package com.basker.pisces.domain.validation.validator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.basker.pisces.domain.constant.DomainConstants.ObjectErrorCode;
import com.basker.pisces.domain.property.meta.StatusProperty;
import com.basker.pisces.domain.validation.ValidationErrors;
import com.basker.pisces.domain.value.StatusValue;
import com.basker.pisces.resource.StringResources;
import com.basker.pisces.service.exception.IObjectErrorsWrapper.ObjectError;

/**
 * 合法状态校验器
 *
 * @author hangwen
 */
public class ValidStatusValidator extends AbstractValidator {

    private String statusProperyAlias;
    private List<Integer> validStatuses;
    private String errorMessagePattern;

    public ValidStatusValidator(String statusProperyAlias, List<Integer> validStatuses, String errorMessagePattern) {
        Assert.hasText(statusProperyAlias, "parameter 'statusProperyAlias' is required");
        Assert.notEmpty(validStatuses, "parameter 'validStatuses' is required");

        this.statusProperyAlias = statusProperyAlias;
        this.validStatuses = new ArrayList<>(validStatuses);
        this.errorMessagePattern = errorMessagePattern;
    }

    @Override
    public List<String> getRequiredPropertyAliasList() {
        StatusProperty statusProperty = this.getStatusProperty();
        Assert.notNull(statusProperty, "Status Property is required");

        return Arrays.asList(statusProperty.getAlias());
    }

    @Override
    public ValidationErrors validate(Object[] dataObjects) {
        StatusProperty statusProperty = this.getStatusProperty();

        ValidationErrors errors = null;

        for (Object dataObject : dataObjects) {
            StatusValue value = statusProperty.getValue(dataObject);
            boolean valid = this.validate(dataObject, value);

            if (!valid) {
                if (errors == null) {
                    errors = new ValidationErrors();
                }

                errors.addError(createError(dataObject, value));
            }
        }

        return errors;
    }

    private ObjectError createError(Object dataObject, StatusValue value) {
        String errorMessage = null;

        if (StringUtils.isEmpty(this.errorMessagePattern)) {
            errorMessage = StringResources.get("pisces-domain.ValidStatusValidator.violation", value.getPresentValue());
        } else {
            errorMessage = StringResources.resolve(this.errorMessagePattern, value.getPresentValue());
        }

        return new ObjectError(ObjectErrorCode.VALID_STATUS_VIOLATION, dataObject, null, errorMessage);
    }

    private StatusProperty getStatusProperty() {
        return (StatusProperty) this.getContext().getEntity().getPropertyByAlias(this.statusProperyAlias, true);
    }

    private boolean validate(Object dataObject, StatusValue value) {
        return validStatuses.stream().anyMatch(status -> Objects.equals(status, value.getDataValue()));
    }
}
